/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cef.repository.repo;

import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.api.authority.AuthorityInfo;
import com.inspur.edp.cef.api.repository.IRootRepository;
import com.inspur.edp.cef.api.repository.RefColumnInfo;
import com.inspur.edp.cef.api.repository.adaptor.IDataAdapterExtendInfo;
import com.inspur.edp.cef.api.repository.dac.IDataTypeDac;
import com.inspur.edp.cef.entity.UQConstraintMediate;
import com.inspur.edp.cef.entity.changeset.IChangeDetail;
import com.inspur.edp.cef.entity.changeset.Tuple;
import com.inspur.edp.cef.entity.condition.EntityFilter;
import com.inspur.edp.cef.entity.condition.NodeSortInfo;
import com.inspur.edp.cef.entity.condition.RetrieveFilter;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.entity.repository.DataSaveParameter;
import com.inspur.edp.cef.entity.repository.DataSaveResult;
import com.inspur.edp.cef.repository.assembler.AbstractDataAdapterExtendInfo;
import com.inspur.edp.cef.repository.dac.ChildEntityDac;
import com.inspur.edp.cef.repository.dac.EntityDac;
import com.inspur.edp.cef.repository.dac.MainEntityDac;
import io.iec.edp.caf.databaseobject.api.entity.TempTableContext;

import java.sql.SQLException;
import java.util.*;

public abstract class BaseRootRepository implements IRootRepository {
	private static final String propName = "ID";
	protected ArrayList<AbstractDataAdapterExtendInfo> extendInfos;

	public final IDataTypeDac getMainDac() {
		MainEntityDac mainDac =  getMainEntityDac();
		if (extendInfos != null)
			mainDac.setExtendInfo(extendInfos);
		return mainDac;
	}

	protected abstract MainEntityDac getMainEntityDac();

	public java.util.List<IEntityData> query(EntityFilter filter, java.util.ArrayList<AuthorityInfo> authorities) {
		return ((MainEntityDac)getMainDac()).query(filter, authorities);
	}

	public final EntityDac getEntityDac(String nodeCode) {
		if (nodeCode == null || nodeCode .equals( "")) {
			return getMainEntityDac();
		}
		MainEntityDac dac = (MainEntityDac)getMainDac();
		if (dac.getNodeCode().equals(nodeCode)) {
			return dac;
		}
		EntityDac childDac = getChildDac(nodeCode, dac);
		if (childDac == null) {
			return dac;
		}
		return childDac;
	}

	private EntityDac getChildDac(String nodeCode, EntityDac dac) {
		for (ChildEntityDac item : dac.innerGetChildDacList()) {
			if (nodeCode.equals(item.getNodeCode())) {
				return item;
			}
			EntityDac childDac = getChildDac(nodeCode, item);
			if (childDac != null) {
				return childDac;
			}
		}
		return null;
	}

	public java.util.List<IEntityData> query(String entityCode, EntityFilter filter, java.util.ArrayList<AuthorityInfo> authorities) {
		checkEntityFilter(filter);
		return getEntityDac(entityCode).query(filter, authorities);
	}

	private void checkEntityFilter(EntityFilter filter)
	{
		if(filter==null||filter.getFieldsFilter()==null)
			return;
		if(filter.getFieldsFilter().isUseFieldsCondition()==false)
			return;
		if(filter.getFieldsFilter().getFilterFields()==null)
			throw new RuntimeException("查询时，查询字段为空。");
		if(filter.getFieldsFilter().getFilterFields().size()==1)
			throw new RuntimeException("目前暂不支持查询一个字段。");
	}

	public IEntityData retrieve(String id) throws SQLException {
		return ((MainEntityDac)getMainDac()).retrieveById(id, null);
	}

	public IEntityData retrieve(String id, java.util.ArrayList<NodeSortInfo> nodeSortConditions) throws SQLException {
		return ((MainEntityDac)getMainDac()).retrieveById(id, nodeSortConditions);
	}

	public IEntityData retrieve(String id,ArrayList<NodeSortInfo> nodeSortInfos,RetrieveFilter retrieveFilter)
	{
        return ((MainEntityDac)getMainDac()).retrieveById(id,nodeSortInfos,retrieveFilter);
	}

	public java.util.List<IEntityData> retrieve(java.util.List<String> idList) throws SQLException {
		return ((MainEntityDac)getMainDac()).retrieveByIds(idList);
	}

	public List<IEntityData> retrieve(List<String> idList,RetrieveFilter retrieveFilter)
	{
		return ((MainEntityDac)getMainDac()).retrieveByIds(idList,retrieveFilter);
	}

	public List<DataSaveResult> save(List<Tuple<IChangeDetail, DataSaveParameter>> changes) throws SQLException{
		return ((MainEntityDac)getMainDac()).save(changes);
	}

	public void save(IChangeDetail[] changes) throws SQLException {
		((MainEntityDac)getMainDac()).save(changes);
	}

	public final String getTableNameByColumns(String nodeCode, java.util.HashMap<String, String> columns, String keyColumnName, RefObject<String> keyDbColumnName, java.util.ArrayList<String> tableAlias) {
		return getEntityDac(nodeCode).getTableNameByColumns(columns, keyColumnName, keyDbColumnName, tableAlias);
	}

	public final String getTableNameByRefColumns(String nodeCode, java.util.HashMap<String, RefColumnInfo> columns, String keyColumnName, RefObject<String> keyDbColumnName, java.util.ArrayList<String> tableAlias) {
		return getEntityDac(nodeCode).getTableNameByRefColumns(columns, keyColumnName, keyDbColumnName, tableAlias);
	}

	public void initParams(java.util.Map<String, Object> pars) {
		getMainDac().initParams(pars);
	}

	public final void initRepoVariables(java.util.HashMap<String, String> vars) {
		((MainEntityDac)getMainDac()).initRepoVariables(vars);
	}

	public final boolean isRef(String nodeCode, String dataId, String propertyName) {
		EntityDac dac = getEntityDac(nodeCode);
		return dac.isRef(dataId,propertyName);
//		EntityFilter filter = new EntityFilter() {
//		};
//		FilterCondition tempVar = new FilterCondition();
//		tempVar.setFilterField(propertyName);
//		tempVar.setValue(dataId);
//		tempVar.setlBracketCount(0);
//		tempVar.setRBracketCount(0);
//		tempVar.setExpresstype(ExpressValueType.Value);
//		tempVar.setCompare(ExpressCompareType.Equal);
//		FilterCondition condition = tempVar;
//		filter.setFilterConditions(new java.util.ArrayList<FilterCondition>(java.util.Arrays.asList(new FilterCondition[]{condition})));

//		if (result == null || result.size() == 0) {
//			return false;
//		}
//		return true;
	}

	public final boolean isEffective(String nodeCode, String dataId) {
		RefObject<java.util.ArrayList<String>> noneEffectiveDatas = new RefObject<>(new ArrayList<>());
		return isDatasEffective(nodeCode, new java.util.ArrayList<String>(java.util.Arrays.asList(new String[]{dataId})), noneEffectiveDatas);
	}

	public final boolean isDatasEffective(String nodeCode, java.util.ArrayList<String> dataIds, RefObject<java.util.ArrayList<String>> noneEffectiveDatas) {
		EntityDac dac = getEntityDac(nodeCode);
		return dac.isDatasEffective(dataIds, noneEffectiveDatas);
	}

	public final boolean isDatasEffective(String nodeCode, java.util.ArrayList<String> dataIds, RefObject<java.util.ArrayList<String>> noneEffectiveDatas, String propName) {
		EntityDac dac = getEntityDac(nodeCode);
		return dac.isDatasEffective(dataIds, noneEffectiveDatas, propName);
	}

	public final void generateTable(String nodeCode) {
		getEntityDac(nodeCode).generateTable();
	}

	public final void dropTable(String nodeCode) {
		getEntityDac(nodeCode).dropTable();
	}

	public final void checkUniqueness(java.util.HashMap<String, java.util.ArrayList<UQConstraintMediate>> constraintInfos) {
		checkUniqueness(constraintInfos, true);
	}

	public final void checkUniqueness(java.util.HashMap<String, java.util.ArrayList<UQConstraintMediate>> constraintInfos, boolean throwEx) {
		for (Map.Entry<String, java.util.ArrayList<UQConstraintMediate>> item : constraintInfos.entrySet()) {
			getEntityDac(item.getKey()).checkUniqueness(item.getValue(), throwEx);
		}
	}

	//region VersionControl

	public Date getVersionControlValue(String dataId) {
		return ((MainEntityDac)getMainDac()).getVersionControlValue(dataId);
	}

	public HashMap<String, Date> getVersionControlValues(List<String> dataIds) {
		return ((MainEntityDac)getMainDac()).getVersionControlValues(dataIds);
	}
	//endregion

	public void addExtendInfo(IDataAdapterExtendInfo extendInfo) {
		if(extendInfos == null)
			extendInfos = new ArrayList<>();
		extendInfos.add((AbstractDataAdapterExtendInfo) extendInfo);
	}

	public TempTableContext createTempTable(String nodeCode)
	{
		return getEntityDac(nodeCode).createTempTable();
	}

	public void dropTempTable(String nodeCode,TempTableContext tempTableContext)
	{
		getEntityDac(nodeCode).dropTempTable(tempTableContext);
	}

	@Override
	public List<String> getDistinctFJM(String fjnPropertyName, EntityFilter filter,ArrayList<AuthorityInfo> authorityInfos,Integer parentLayer) {
		return getMainEntityDac().getDistinctFJM(fjnPropertyName,filter,authorityInfos,parentLayer);
	}
}
